//! 数字生成器模块

use rand::Rng;

/// 生成指定范围的整数
pub fn integer(min: i64, max: i64) -> i64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成指定范围的浮点数
pub fn float(min: f64, max: f64) -> f64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成指定精度的浮点数
pub fn float_with_precision(min: f64, max: f64, precision: usize) -> f64 {
    let value = float(min, max);
    let multiplier = 10_f64.powi(precision as i32);
    (value * multiplier).round() / multiplier
}

/// 生成正整数
pub fn positive_integer(max: i64) -> i64 {
    integer(1, max)
}

/// 生成负整数
pub fn negative_integer(min: i64) -> i64 {
    integer(min, -1)
}

/// 生成百分比（0-100）
pub fn percentage() -> f64 {
    float(0.0, 100.0)
}

/// 生成概率值（0.0-1.0）
pub fn probability() -> f64 {
    float(0.0, 1.0)
}

/// 生成货币金额
pub fn currency(min: f64, max: f64) -> f64 {
    float_with_precision(min, max, 2)
}

/// 生成年龄
pub fn age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(1..=120)
}

/// 生成成人年龄（18-80）
pub fn adult_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(18..=80)
}

/// 生成儿童年龄（1-17）
pub fn child_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(1..=17)
}

/// 生成分数（0-100）
pub fn score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(0..=100)
}

/// 生成及格分数（60-100）
pub fn passing_score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(60..=100)
}

/// 生成不及格分数（0-59）
pub fn failing_score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(0..=59)
}

/// 生成温度（摄氏度）
pub fn temperature_celsius() -> f64 {
    float_with_precision(-50.0, 50.0, 1)
}

/// 生成温度（华氏度）
pub fn temperature_fahrenheit() -> f64 {
    float_with_precision(-58.0, 122.0, 1)
}

/// 生成身高（厘米）
pub fn height_cm() -> u16 {
    let mut rng = rand::thread_rng();
    rng.gen_range(140..=220)
}

/// 生成体重（公斤）
pub fn weight_kg() -> f64 {
    float_with_precision(40.0, 150.0, 1)
}

/// 生成BMI指数
pub fn bmi() -> f64 {
    float_with_precision(15.0, 40.0, 1)
}

/// 生成银行卡号（16位）
pub fn credit_card_number() -> String {
    let mut rng = rand::thread_rng();
    (0..16)
        .map(|_| rng.gen_range(0..=9).to_string())
        .collect::<Vec<_>>()
        .join("")
}

/// 生成手机号码（中国）
pub fn phone_number_cn() -> String {
    let mut rng = rand::thread_rng();
    let prefixes = ["130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
                   "150", "151", "152", "153", "155", "156", "157", "158", "159",
                   "180", "181", "182", "183", "184", "185", "186", "187", "188", "189"];
    
    let prefix = prefixes[rng.gen_range(0..prefixes.len())];
    let suffix: String = (0..8)
        .map(|_| rng.gen_range(0..=9).to_string())
        .collect();
    
    format!("{}{}", prefix, suffix)
}

/// 生成身份证号码（中国，18位）
pub fn id_card_cn() -> String {
    let mut rng = rand::thread_rng();
    
    // 地区代码（前6位）
    let area_codes = ["110000", "120000", "130000", "140000", "150000", "210000"];
    let area_code = area_codes[rng.gen_range(0..area_codes.len())];
    
    // 出生日期（8位）
    let year = rng.gen_range(1950..=2005);
    let month = rng.gen_range(1..=12);
    let day = rng.gen_range(1..=28);
    let birth_date = format!("{:04}{:02}{:02}", year, month, day);
    
    // 顺序码（3位）
    let sequence = format!("{:03}", rng.gen_range(1..=999));
    
    // 前17位
    let first_17 = format!("{}{}{}", area_code, birth_date, sequence);
    
    // 校验码（第18位）
    let check_digit = calculate_id_check_digit(&first_17);
    
    format!("{}{}", first_17, check_digit)
}

/// 计算身份证校验码
fn calculate_id_check_digit(first_17: &str) -> char {
    let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    let check_chars = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    
    let sum: usize = first_17
        .chars()
        .enumerate()
        .map(|(i, c)| c.to_digit(10).unwrap() as usize * weights[i])
        .sum();
    
    check_chars[sum % 11]
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_integer() {
        let num = integer(1, 10);
        assert!(num >= 1 && num <= 10);
    }

    #[test]
    fn test_float_with_precision() {
        let num = float_with_precision(1.0, 2.0, 2);
        let decimal_places = format!("{:.10}", num).split('.').nth(1).unwrap().trim_end_matches('0').len();
        assert!(decimal_places <= 2);
    }

    #[test]
    fn test_adult_age() {
        let age = adult_age();
        assert!(age >= 18 && age <= 80);
    }

    #[test]
    fn test_phone_number_cn() {
        let phone = phone_number_cn();
        assert_eq!(phone.len(), 11);
        assert!(phone.starts_with('1'));
    }

    #[test]
    fn test_id_card_cn() {
        let id = id_card_cn();
        assert_eq!(id.len(), 18);
        assert!(id.chars().take(17).all(|c| c.is_ascii_digit()));
    }

    #[test]
    fn test_credit_card_number() {
        let card = credit_card_number();
        assert_eq!(card.len(), 16);
        assert!(card.chars().all(|c| c.is_ascii_digit()));
    }
}